#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
DeepSeek API封装模块
负责调用DeepSeek文本大模型API，对视觉分析结果进行补充和完善
"""

import os
import json
import requests
import pandas as pd
import logging
from typing import Dict, Any, Optional
from datetime import datetime
from ..config.config_manager import category_config_manager
from ..vision.error_handler import retry_decorator, ApiErrorHandler

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
)
logger = logging.getLogger(__name__)


class DeepSeekTextCompleter:
    """
    DeepSeek文本补充分析器
    调用DeepSeek文本大模型API，对视觉分析结果进行智能补充和推断
    """
    
    def __init__(self, api_key: str, sample_data_path: str):
        """
        初始化文本补充器
        
        Args:
            api_key: DeepSeek API密钥
            sample_data_path: 样本数据文件路径
        """
        self.api_key = api_key
        self.sample_data_path = sample_data_path
        self.api_base_url = "https://api.deepseek.com/v1/chat/completions"
        self.sample_data = self.load_sample_data()
        
        # 初始化错误处理器
        self.error_handler = ApiErrorHandler(max_retries=3, base_delay=1.0)
        
        logger.info(f"DeepSeekTextCompleter初始化完成，样本数据记录数: {len(self.sample_data) if self.sample_data is not None else 0}")
    
    def load_sample_data(self) -> Optional[pd.DataFrame]:
        """
        加载样本数据
        
        Returns:
            pandas.DataFrame: 样本数据，如果文件不存在则返回None
        """
        try:
            if not os.path.exists(self.sample_data_path):
                logger.warning(f"样本数据文件不存在: {self.sample_data_path}")
                return None
            
            df = pd.read_csv(self.sample_data_path, encoding='utf-8')
            logger.info(f"成功加载样本数据，共{len(df)}条记录")
            return df
        except Exception as e:
            logger.error(f"加载样本数据失败: {str(e)}")
            return None
    
    def find_video_sample(self, video_id: str) -> Optional[Dict[str, Any]]:
        """
        查找特定视频ID的样本数据
        
        Args:
            video_id: 视频ID
            
        Returns:
            dict: 样本数据记录，如果未找到则返回None
        """
        if self.sample_data is None or self.sample_data.empty:
            return None
        
        try:
            # 尝试多种可能的列名查找
            possible_id_columns = ['视频ID', 'video_id', 'id', '视频编码']
            
            for col in possible_id_columns:
                if col in self.sample_data.columns:
                    matches = self.sample_data[self.sample_data[col] == video_id]
                    if not matches.empty:
                        return matches.iloc[0].to_dict()
            
            logger.info(f"未找到视频ID {video_id} 的样本数据")
            return None
        except Exception as e:
            logger.error(f"查找样本数据失败: {str(e)}")
            return None
    
    def generate_supplement_prompt(self, video_id: str, vision_results: Dict[str, Any], 
                                  sample_record: Optional[Dict[str, Any]] = None) -> str:
        """
        生成补充分析的提示词
        
        Args:
            video_id: 视频ID
            vision_results: 视觉分析结果
            sample_record: 样本数据记录
            
        Returns:
            str: 提示词
        """
        try:
            # 识别需要补充的字段（置信度低或缺失的字段）
            fields_to_supplement = []
            for category, result in vision_results.get('analysis', {}).items():
                if isinstance(result, dict):
                    confidence = result.get('confidence', 100)
                    value = result.get('value')
                    # 如果置信度低于阈值或值为None，则需要补充
                    if confidence < 80 or value is None or value == '':
                        fields_to_supplement.append({
                            'category': category,
                            'current_value': value,
                            'confidence': confidence
                        })
            
            # 生成提示词
            prompt = f"""你是一个专业的视频内容分析助手，请根据提供的信息对以下视频进行智能分析和推断。

视频ID: {video_id}

"""
            
            # 添加视觉分析结果
            prompt += "\n## 视觉分析结果\n"
            for category, result in vision_results.get('analysis', {}).items():
                if isinstance(result, dict):
                    value = result.get('value', '未识别')
                    confidence = result.get('confidence', 100)
                    prompt += f"- {category}: {value} (置信度: {confidence}%)\n"
                else:
                    prompt += f"- {category}: {result}\n"
            
            # 添加样本数据（如果有）
            if sample_record:
                prompt += "\n## 相关样本数据\n"
                # 只添加可能有用的字段
                for key, value in sample_record.items():
                    if pd.notna(value) and str(value).strip():
                        prompt += f"- {key}: {value}\n"
            
            # 明确需要补充的字段
            if fields_to_supplement:
                prompt += "\n## 需要补充分析的字段\n"
                for field in fields_to_supplement:
                    prompt += f"- {field['category']}: 当前值 '{field['current_value']}'，置信度 {field['confidence']}%\n"
            
            # 添加任务指令
            prompt += """

请基于以上信息，对视频内容进行全面分析，并针对标记为需要补充的字段提供更准确的推断结果。

请以JSON格式返回你的分析结果，格式如下：
{
  "supplement_fields": {
    "字段名1": {
      "value": "推断的值",
      "confidence": 置信度（0-100）,
      "reasoning": "推断理由"
    },
    "字段名2": {
      ...
    }
  },
  "overall_analysis": "对视频内容的整体分析和总结"
}

请确保JSON格式正确，不要包含任何额外的解释或说明文字。
"""
            
            return prompt
        except Exception as e:
            logger.error(f"生成提示词失败: {str(e)}")
            # 返回一个基础提示词
            return f"请分析视频ID {video_id} 的内容，并提供详细的编码分析结果。"
    
    @retry_decorator(max_retries=3, delay=1.0, exponential_backoff=True)
    def call_deepseek_api(self, prompt: str) -> Dict[str, Any]:
        """
        调用DeepSeek文本API
        
        Args:
            prompt: 提示词
            
        Returns:
            dict: API返回结果
            
        Raises:
            Exception: API调用失败时抛出异常
        """
        try:
            headers = {
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}"
            }
            
            payload = {
                "model": "deepseek-chat",
                "messages": [
                    {
                        "role": "system",
                        "content": "你是一个专业的视频内容分析助手，擅长基于已有信息进行智能推断和补充分析。"
                    },
                    {
                        "role": "user",
                        "content": prompt
                    }
                ],
                "temperature": 0.3,
                "max_tokens": 2000
            }
            
            # 使用错误处理器执行请求
            response = self.error_handler.execute_request(
                lambda: requests.post(
                    self.api_base_url,
                    headers=headers,
                    json=payload,
                    timeout=30
                )
            )
            
            # 检查响应状态
            response.raise_for_status()
            
            result = response.json()
            logger.debug(f"DeepSeek API调用成功，返回结果大小: {len(str(result))} 字节")
            
            return result
            
        except requests.exceptions.RequestException as e:
            logger.error(f"DeepSeek API请求异常: {str(e)}")
            raise
        except Exception as e:
            logger.error(f"DeepSeek API调用失败: {str(e)}")
            raise
    
    def parse_supplement_response(self, response: Dict[str, Any]) -> Dict[str, Any]:
        """
        解析补充分析结果
        
        Args:
            response: API返回的原始结果
            
        Returns:
            dict: 解析后的补充结果
        """
        try:
            # 提取模型响应内容
            if 'choices' in response and len(response['choices']) > 0:
                message = response['choices'][0].get('message', {})
                content = message.get('content', '')
                
                # 尝试解析JSON格式
                try:
                    parsed_result = json.loads(content)
                    return parsed_result
                except json.JSONDecodeError:
                    # 如果JSON解析失败，尝试提取其中的JSON部分
                    logger.warning("响应内容不是有效的JSON，尝试提取JSON部分")
                    
                    # 简单尝试提取花括号之间的内容
                    import re
                    json_match = re.search(r'\{[\s\S]*\}', content)
                    if json_match:
                        try:
                            parsed_result = json.loads(json_match.group())
                            return parsed_result
                        except json.JSONDecodeError:
                            logger.error("无法从响应中提取有效的JSON")
                
                # 如果都失败，返回一个基础结构
                return {
                    "supplement_fields": {},
                    "overall_analysis": content
                }
            
            logger.error("无效的API响应格式")
            return {
                "supplement_fields": {},
                "overall_analysis": "无法解析API响应"
            }
            
        except Exception as e:
            logger.error(f"解析补充分析结果失败: {str(e)}")
            return {
                "supplement_fields": {},
                "overall_analysis": f"解析错误: {str(e)}"
            }
    
    def supplement_analysis(self, video_id: str, vision_results: Dict[str, Any]) -> Dict[str, Any]:
        """
        补充分析结果
        
        Args:
            video_id: 视频ID
            vision_results: 视觉分析结果
            
        Returns:
            dict: 补充后的结果
        """
        try:
            logger.info(f"开始对视频 {video_id} 进行文本补充分析")
            
            # 1. 查找样本数据
            sample_record = self.find_video_sample(video_id)
            
            # 2. 生成提示词
            prompt = self.generate_supplement_prompt(video_id, vision_results, sample_record)
            
            # 3. 调用文本大模型
            api_response = self.call_deepseek_api(prompt)
            
            # 4. 解析结果
            supplement_results = self.parse_supplement_response(api_response)
            
            # 5. 合并结果
            final_results = self.merge_results(vision_results, supplement_results)
            
            logger.info(f"视频 {video_id} 文本补充分析完成")
            return final_results
            
        except Exception as e:
            logger.error(f"视频 {video_id} 文本补充分析失败: {str(e)}")
            # 返回原始视觉结果，添加错误信息
            vision_results['text_supplement_error'] = str(e)
            vision_results['text_supplement_timestamp'] = datetime.now().isoformat()
            return vision_results
    
    def merge_results(self, vision_results: Dict[str, Any], supplement_results: Dict[str, Any]) -> Dict[str, Any]:
        """
        合并视觉分析和文本补充结果
        
        Args:
            vision_results: 视觉分析结果
            supplement_results: 文本补充结果
            
        Returns:
            dict: 合并后的完整结果
        """
        try:
            # 深拷贝原始结果，避免修改原数据
            import copy
            merged_results = copy.deepcopy(vision_results)
            
            # 确保analysis字段存在
            if 'analysis' not in merged_results:
                merged_results['analysis'] = {}
            
            # 添加文本补充字段
            merged_results['text_supplement'] = {
                'timestamp': datetime.now().isoformat(),
                'overall_analysis': supplement_results.get('overall_analysis', ''),
                'supplemented_fields': []
            }
            
            # 合并补充字段
            supplement_fields = supplement_results.get('supplement_fields', {})
            for field_name, field_data in supplement_fields.items():
                # 只更新置信度更高的结果
                current_value = merged_results['analysis'].get(field_name, {})
                current_confidence = current_value.get('confidence', 0) if isinstance(current_value, dict) else 0
                supplement_confidence = field_data.get('confidence', 0)
                
                if supplement_confidence > current_confidence:
                    # 保存原始值（如果有）
                    original_value = None
                    original_confidence = None
                    if isinstance(current_value, dict):
                        original_value = current_value.get('value')
                        original_confidence = current_value.get('confidence')
                    
                    # 更新为新值
                    merged_results['analysis'][field_name] = {
                        'value': field_data.get('value'),
                        'confidence': supplement_confidence,
                        'source': 'text_supplement',
                        'reasoning': field_data.get('reasoning', '')
                    }
                    
                    # 记录被补充的字段
                    merged_results['text_supplement']['supplemented_fields'].append({
                        'field_name': field_name,
                        'original_value': original_value,
                        'original_confidence': original_confidence,
                        'new_value': field_data.get('value'),
                        'new_confidence': supplement_confidence
                    })
            
            logger.info(f"成功合并结果，补充了 {len(merged_results['text_supplement']['supplemented_fields'])} 个字段")
            return merged_results
            
        except Exception as e:
            logger.error(f"合并结果失败: {str(e)}")
            # 发生错误时返回原始视觉结果
            return vision_results


# 创建全局实例
_text_completer_instance = None

def get_text_completer(api_key: str = None, sample_data_path: str = None) -> DeepSeekTextCompleter:
    """
    获取文本补充器实例（单例模式）
    
    Args:
        api_key: DeepSeek API密钥
        sample_data_path: 样本数据文件路径
        
    Returns:
        DeepSeekTextCompleter: 文本补充器实例
    """
    global _text_completer_instance
    
    if _text_completer_instance is None:
        if not api_key:
            api_key = os.environ.get('DEEPSEEK_API_KEY', '')
        if not sample_data_path:
            # 默认样本数据路径
            sample_data_path = os.path.join(
                os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
                'data', '样本数据表.csv'
            )
        
        _text_completer_instance = DeepSeekTextCompleter(api_key, sample_data_path)
    
    return _text_completer_instance


if __name__ == '__main__':
    try:
        # 测试代码
        print("DeepSeekTextCompleter测试")
        
        # 从环境变量获取API密钥
        api_key = os.environ.get('DEEPSEEK_API_KEY', '')
        if not api_key:
            print("警告: 未设置DEEPSEEK_API_KEY环境变量")
            api_key = "your_api_key_here"  # 仅用于测试
        
        # 创建实例
        completer = DeepSeekTextCompleter(
            api_key=api_key,
            sample_data_path="../../data/样本数据表.csv"
        )
        
        print("测试完成")
        
    except Exception as e:
        print(f"测试失败: {str(e)}")